#ifndef TOKEN_H
#define TOKEN_H
#include <string>
#include <cassert>
#include <iostream>
#include <vector>
class TokenBlock;
class TokenSenIf;
class TokenSenWhile;
class Context
{
	std::istream* is;
	std::ostream* os;
	std::ostream* oerr;
	std::ostream* olog;
	bool prompt;
	int row;
	bool end;
	std::vector<std::string> indent; // every level contains its ancestor
	std::vector<std::string> source;
	std::string removeComment(const std::string& raw) const;
	std::string nextLine();
	void rollbackLine()	{assert(row >= 1); row--;}
	void setRow(int Row) {assert(Row >= 0); row = Row;}
	int getRow() {return row;}
	std::ostream& stdOut() {return *os;}
	std::ostream& stdErr() {return *oerr;}
	std::ostream& stdLog() {return *olog;}
	static Context* instance;
	Context(std::istream* Is, bool Prompt = true, std::ostream* Os = &std::cout, std::ostream* Oerr = &std::cerr, std::ostream* Olog = &std::clog)
		: row(0), end(false), is(Is), prompt(Prompt), os(Os), oerr(Oerr), olog(Olog)
		{indent.push_back(std::string(""));}
	Context(const Context&);
public:
	static void init(std::istream* Is, bool Prompt = true)
	{
		assert(instance == NULL);
		instance = new Context(Is, Prompt);
	}
	static Context* getInstance()
	{
		assert(instance != NULL);
		return instance;
	}
	static void del()
	{
		delete instance;
	}
	void resetIndent() // called when an error throwed to main
	{
		while (indent.size() > 1)
			indent.pop_back();
	}
	friend class TokenBlock; 
	friend class TokenSenIf;
	friend class TokenSenWhile;
	friend class TokenSen;
	friend class TokenSenPrint;
	friend class Error;
};
class Token
{
protected:
	std::string toParse;
public:
	Token(const std::string& ToParse = ""): toParse(ToParse) {}//{std::clog << "--toParse: " << toParse << std::endl;}
	virtual void run(bool enabled=true) = 0;
	//~Token() {std::clog << "++Parsed: " << toParse << std::endl;}
};
#endif

